package com.ce.pms.house.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.ce.pms.base.service.impl.PmsBaseServiceImpl;
import com.ce.pms.charge.dao.IAccountDao;
import com.ce.pms.charge.dao.IBankAccountDao;
import com.ce.pms.charge.dao.IMeterDataRegisterDao;
import com.ce.pms.charge.dao.ISubAccountDao;
import com.ce.pms.charge.model.AccountDomain;
import com.ce.pms.charge.model.BankAccountDomain;
import com.ce.pms.charge.model.ChargeAccountDomain;
import com.ce.pms.charge.model.ChargeDatasDomain;
import com.ce.pms.charge.service.IAccountService;
import com.ce.pms.charge.service.IArCalculateService;
import com.ce.pms.charge.service.IBankCollectionService;
import com.ce.pms.charge.service.IMeterDataRegisterService;
import com.ce.pms.charge.service.ISubAccountService;
import com.ce.pms.charge.service.ITransactionService;
import com.ce.pms.charge.vo.OriginalMeterDataVO;
import com.ce.pms.common.dao.ISecUserDao;
import com.ce.pms.common.model.SysrefcodeDO;
import com.ce.pms.common.util.StringAnalysiUtil;
import com.ce.pms.customer.dao.IClientRHouseDao;
import com.ce.pms.customer.dao.IProRightDao;
import com.ce.pms.customer.model.ClientRHouseDO;
import com.ce.pms.customer.model.ProRightDO;
import com.ce.pms.exception.BusinessException;
import com.ce.pms.house.dao.ICoalitionHouseDao;
import com.ce.pms.house.dao.ICopyMeterDataDao;
import com.ce.pms.house.dao.IExamineApproveDao;
import com.ce.pms.house.dao.IGoOutDao;
import com.ce.pms.house.dao.IGoodsRecordDao;
import com.ce.pms.house.dao.IHouseDao;
import com.ce.pms.house.dao.IMeterDao;
import com.ce.pms.house.dao.IReasonDefDao;
import com.ce.pms.house.model.CopyMeterData;
import com.ce.pms.house.model.ExamineApproveDomain;
import com.ce.pms.house.model.GoOutDomain;
import com.ce.pms.house.model.GoodsRecordDomain;
import com.ce.pms.house.service.IHouseService;
import com.ce.pms.house.service.IProRightChangeService;
import com.ce.pms.house.vo.ExamineApproveVO;
import com.ce.pms.house.vo.GoOutVO;
import com.ce.util.BlankUtil;
import com.sitechasia.webx.core.support.Page;
import com.sitechasia.webx.core.utils.base.PopulateUtil;
/**
 * 功能描述: 产权变更功能处理类
 * <p>版权所有：中企动力
 * <p>未经本公司许可，不得以任何方式复制或使用本程序任何部分
 *
 * @author  胡煦
 * Create on:2008-9-12
 * Edit author:
 * Edit on:
 * 修改原因：

 */

public class ProRightChangeServiceImpl extends PmsBaseServiceImpl implements
		IProRightChangeService {
	/**
	 * 方法描述: 退伙列表页面查询方法,根据传入参数不同执行不同操作，例如：
	 * 1：查询全部，默认按ID降序排序
	 * 2：房号+业主姓名：根据房号，业主名字进行模糊查询，默认按ID降序排序
	 * 3：房号+业主姓名+排序参数：根据房号，业主名字进行模糊查询，然后根据order排序
	 * 4：排序参数：查询全部，然后根据order排序
	 * @author 胡煦
	 * Create on:2008-8-28
	 * @param String houseNumber,String owerName,String order,int currentPage,int pageSize
	 * @return Page
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public Page queryGoOutDoListByPage(String houseNumber,String owerName,String order,int currentPage,int pageSize){
		List<GoOutVO> GoOutVOList = new ArrayList<GoOutVO>();
		Page page = goOutDao.queryGoOutDoListByPage(null,houseNumber, owerName, order, currentPage, pageSize);
		List<GoOutDomain> goOutDomainList = page.getResult();
		for(GoOutDomain goOutDomain : goOutDomainList){
			GoOutVO goOutVO = this.convertGoOutDoToVo(goOutDomain);
			GoOutVOList.add(goOutVO);
		}
		page.setResult(GoOutVOList);
		return page;
	}

	/**
	 * 方法描述:验证手工输入的房号,并返回其状态
	 * 如果用户输入的房号已经存在退伙审批表且其状态不为退伙结束,则不允许
	 * @author 胡煦
	 * Create on:2008-9-17
	 * @param houseId
	 * @return SysrefcodeDO:返回不为空说明处于退伙中，否则说明没有处于
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public String checkTheHouseNumber(Long houseId){
		SysrefcodeDO sysrefcodeDO = goOutDao.queryHouseInGoOutBy(houseId);
		return sysrefcodeDO==null?null:sysrefcodeDO.getValue();
	}

	/**
	 * 方法描述: 产权变更历史查询方法
	 * 1：操作人,查询某个角色操作的全部历史信息，默认按ID降序排序
	 * 2: 楼栋ID+房号+fitlerStr+排序参数：精确查询某楼栋和模糊查询房号,而且退伙流程阶段已经处于退伙结束的,然后根据order排序
	 * 3: 房号+fitlerStr或者楼栋ID+fitlerStr：精确查询某楼栋或模糊查询房号,而且退伙流程阶段已经处于退伙结束的
	 * @author 胡煦
	 * Create on:2008-8-29
	 * @param String buildingId,String houseNumber,String order,int currentPage,int pageSize
	 * @return Page
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */

	public Page queryHisGoOutDoListByPage(Long buildingId,String houseNumber,String order,Long createId,int currentPage,int pageSize){
		List<GoOutVO> GoOutVOList = new ArrayList<GoOutVO>();
		Page page = goOutDao.queryGoOutDoListByPage(buildingId,houseNumber,null, order,currentPage, pageSize);
		List<GoOutDomain> goOutDomainList = page.getResult();
		for(GoOutDomain goOutDomain : goOutDomainList){
			GoOutVO goOutVO = this.convertGoOutDoToVo(goOutDomain);
			//设置变更后的业主姓名字符串
			goOutVO.setNewClients(houseService.getOwnerNameBy(goOutDomain.getHouse().getHouseNumber()));
			//设置变更前房产证号
			ProRightDO proRightDO = proRightDao.getLastProRightByHouseId(goOutDomain.getHouse().getKeyword());
			goOutVO.setHousePropertyNo(proRightDO==null?null:proRightDO.getProRightNO());
			//设置变更后的房产证号
			ProRightDO newProRightDO = proRightDao.getEffectiveProRightByHouseId(goOutDomain.getHouse().getKeyword());
			goOutVO.setNewHousePropertyNo(newProRightDO==null?null:newProRightDO.getProRightNO());
			//获取产权变更时间
			goOutVO.setOutDate(proRightDO==null?null:proRightDO.getSysInfo().getModifyDate());
			GoOutVOList.add(goOutVO);
		}
		page.setResult(GoOutVOList);
		return page;
	}

	/**
	 * 方法描述: 根据id查询GoOutVO
	 * @author 胡煦
	 * Create on:2008-9-4
	 * @param goOutId
	 * @return GoOutVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public GoOutVO findGoOutVOById(Long goOutId){
		GoOutDomain goOutDomain = goOutDao.findById(goOutId);
		GoOutVO goOutVO = this.convertGoOutDoToVo(goOutDomain);
		//设置费用审批人
		ExamineApproveDomain chargeCheckerDomain = examineApproveDao.getExamineApproveBy(goOutVO.getKeyword(), SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_FINANCE);
		goOutVO.setChargeChecker(secUserDao.queryUserNameById(chargeCheckerDomain==null?null:chargeCheckerDomain.getUserId()));
		goOutVO.setChargeCheckerId(chargeCheckerDomain==null?null:chargeCheckerDomain.getUserId());
		//设置退伙手续审批人
		ExamineApproveDomain outCheckerDomain = examineApproveDao.getExamineApproveBy(goOutVO.getKeyword(), SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_CLIENT);
		goOutVO.setOutChecker(secUserDao.queryUserNameById(outCheckerDomain==null?null:outCheckerDomain.getUserId()));
		goOutVO.setOutCheckerId(outCheckerDomain==null?null:outCheckerDomain.getUserId());
		return goOutVO;
	}

	/**
	 * 方法描述: 根据退伙申请记录id查询退伙审核记录
	 * @author 胡煦
	 * Create on:2008-9-4
	 * @param goOutId
	 * @return Map
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public Map<String, ExamineApproveVO> findExamineApprovesById(Long goOutId){
		Map<String, ExamineApproveVO> map = new HashMap<String, ExamineApproveVO>();
		ExamineApproveDomain approveDomain1 = examineApproveDao.getExamineApproveBy(goOutId, SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_CLIENT);
		ExamineApproveDomain approveDomain2 = examineApproveDao.getExamineApproveBy(goOutId, SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_FINANCE);
		map.put("001",convertGoOutDoToVo(approveDomain1) );
		map.put("002",convertGoOutDoToVo(approveDomain2) );
		return map;
	}

	/**
	 * 方法描述: 退伙申请增加
	 * @author 胡煦
	 * Create on:2008-9-2
	 * @param GoOutVO
	 * @return GoOutVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public GoOutVO addGoOutRequisition(GoOutVO goOutVO){
		//验证用户请求退伙的房间是否符合要求
		checkTheGoOutRecorder(goOutVO);
		if(!BlankUtil.isBlank(goOutVO.getCopyMeterWaterReading())){
			//新增水表读数
			goOutVO.setCopyMeterWaterId(addMeterData(goOutVO, SysrefcodeDO.HM_WATER_METER_TYPE_CODE).getKeyword());
		}
		if(!BlankUtil.isBlank(goOutVO.getCopyMeterAmmeterReading())){
			//新增电表读数
			goOutVO.setCopyMeterAmmeterId(addMeterData(goOutVO, SysrefcodeDO.HM_AMMETER_METER_TYPE_CODE).getKeyword());
		}

		GoOutDomain goOutDomain = convertGoOutVoToDo(goOutVO);
		//设置退伙状态
		goOutDomain.setGoOutStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_GO_OUT_FLOW, SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_WAIT));
		goOutDomain = goOutDao.saveObject(goOutDomain);
		goOutVO.setKeyword(goOutDomain.getKeyword());
		//建立退伙审核记录
		goOutVO = addExamineApprove(goOutVO);
		return goOutVO;
	}


	/**
	 * 方法描述: 退伙申请修改
	 * @author 胡煦
	 * Create on:2008-9-2
	 * @param GoOutVO
	 * @return GoOutVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	public GoOutVO editGoOutRequisition(GoOutVO goOutVO){

		GoOutDomain goOutDomain = goOutDao.findById(goOutVO.getKeyword());
		//只能修改新建状态的退伙记录（该新建状态的记录主要由审核不通过和反审核操作产生）
		if(!goOutDomain.getGoOutStatus().getValue().equals(SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_NEW)){
			throw new BusinessException("house:house_goout_status_exception",
					BusinessException.WARNING);
		}
		goOutVO.setClients(goOutDomain.getClients());
		PopulateUtil.populate(goOutVO, goOutDomain);
		GoOutDomain goOutDomain2 = convertGoOutVoToDo(goOutVO);
		modifyInfo(goOutDomain.getSysInfo(), goOutVO.getModifierId());
		goOutDomain.setGoods(goOutDomain2.getGoods());
		goOutDomain.setReasonDef1(goOutDomain2.getReasonDef1());
		goOutDomain.setReasonDef2(goOutDomain2.getReasonDef2());
		goOutDomain.setReasonDef3(goOutDomain2.getReasonDef3());
		//修改水表读数
		CopyMeterData copyMeterData1 = editMeterDataByType(goOutVO, goOutDomain.getCopyMeterData1(), SysrefcodeDO.HM_WATER_METER_TYPE_CODE, goOutVO.getCopyMeterWaterReading());
		goOutDomain.setCopyMeterData1(copyMeterData1);
		goOutVO.setCopyMeterWaterId(copyMeterData1 == null?null:copyMeterData1.getKeyword());
		//修改电表读数
		CopyMeterData copyMeterData2 = editMeterDataByType(goOutVO, goOutDomain.getCopyMeterData2(), SysrefcodeDO.HM_AMMETER_METER_TYPE_CODE, goOutVO.getCopyMeterAmmeterReading());
		goOutDomain.setCopyMeterData2(copyMeterData2);
		goOutVO.setCopyMeterAmmeterId(copyMeterData2 == null?null:copyMeterData2.getKeyword());
		//修改退伙审核记录
		goOutVO = this.editExamineApprove(goOutVO);
		//设置退伙状态
		goOutDomain.setGoOutStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_GO_OUT_FLOW, SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_WAIT));
		goOutDomain.setCopyMeterDate(goOutVO.getCopyTime());
		goOutDomain = goOutDao.updateObject(goOutDomain);

		return goOutVO;
	}
	/**
	 * 方法描述: 退伙申请提交
	 * @author 胡煦
	 * Create on:2008-9-2
	 * @param Long goOutId,Long creater
	 * @return GoOutVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public GoOutVO referGoOutRequisition(Long goOutId,Long creater){
		 GoOutDomain goOutDomain = goOutDao.findById(goOutId);
		 //只能提交新建状态的退伙记录（该新建状态的记录主要由审核不通过和反审核操作产生）
		 if(!goOutDomain.getGoOutStatus().getValue().equals(SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_NEW)){
			throw new BusinessException("house:house_goout_status_exception",
					BusinessException.WARNING);
		 }
		 //更新退伙登记的状态
		 goOutDomain.setGoOutStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_GO_OUT_FLOW, SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_WAIT));
		 modifyInfo(goOutDomain.getSysInfo(), creater);
		 GoOutVO goOutVO = new GoOutVO();
		 goOutVO.setKeyword(goOutId);
		 goOutVO.setModifierId(creater);
		 //修改退伙审核表
		 this.editExamineApprove(goOutVO);
		 return convertGoOutDoToVo(goOutDomain);
	 }

	 /**
	 * 方法描述: 查询当前数据库时间
	 * @author 胡煦
	 * Create on:2008-12-16
	 * @param
	 * @return Date
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public Date getDataBaseDate(){
		 return this.getDate();
	 }


	 /**
	 * 方法描述: 验证要退伙的产权房与管理房之间是否有关系
	 * @author 胡煦
	 * Create on:2008-9-9
	 * @param houseId
	 * @return boolean:true说明有关系,反之说明没有
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public boolean checkTheManagerHouse(Long houseId){
		 return coalitionHouseDao.getCoalitionHouseByHouseId(houseId)!= null;
	 }

	 /**
	 * 方法描述: 验证该产权房拥有正确有效的帐户
	 * @author 胡煦
	 * Create on:2008-9-9
	 * @param houseId
	 * @return boolean:true说明拥有正确有效的帐户,反之说明没有
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public boolean checkTheValidAccount(Long houseId){
		 ProRightDO proRightDO = proRightDao.getEffectiveProRightByHouseId(houseId);
		 if(BlankUtil.isBlank(proRightDO)){
			 return false;
		 }else{
			return accountDao.getAccountBy(proRightDO.getProRightId(), houseId, true) != null;
		 }
	 }

	 /**
	 * 方法描述: 验证该产权房的帐户是否存在挂起交易
	 * @author 胡煦
	 * Create on:2008-12-1
	 * @param houseId
	 * @return void
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 private void checkTheGoOutHasHangS(Long houseId){

		 ProRightDO proRightDO = proRightDao.getEffectiveProRightByHouseId(houseId);
		 if(BlankUtil.isBlank(proRightDO)){
			 throw new BusinessException("house:pro_right_account_error_exception",
						BusinessException.WARNING);
		 }else{
			AccountDomain accountDomain = accountDao.getAccountBy(proRightDO.getProRightId(), houseId, true);
			if(!BlankUtil.isBlank(accountDomain)){
				if(transactionService.checkAccountHasHangsTransaction(accountDomain.getAccountId())){
					throw new BusinessException("house:pro_right_account_hashangs_exception",
							BusinessException.WARNING);
				}
			}
		 }
	 }

	 /**
	 * 方法描述: 验证:A、如果要退伙的产权房与管理房之间有关系，必须先解除管理房和产权房之间的关系（目前解除的同时，要结清所有费用， 以后需要提供帐户之间的转帐功能），否则不能退伙操作。
		B、该产权房拥有正确有效的帐户和银行划款账号。
	 * @author 胡煦
	 * Create on:2008-9-9
	 * @param goOutVO
	 * @return void
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 private void checkTheGoOutRecorder(GoOutVO goOutVO){
		 Long houseId = goOutVO.getHouseId();
		 //验证要退伙的产权房与管理房之间是否有关系
		 if(checkTheManagerHouse(houseId)){
			 throw new BusinessException("house:pro_right_number_exist_ship_exception",
						BusinessException.WARNING);
		 }
		 //验证该产权房的帐户是否存在挂起交易
		 this.checkTheGoOutHasHangS(houseId);
//		 //验证该产权房拥有正确有效的帐户
//		 if(!checkTheValidAccount(houseId)){
//			 throw new BusinessException("house:pro_right_account_error_exception",
//						BusinessException.WARNING);
//		 }
//		 //验证该产权房拥有正确有效的银行划款账号
//		 if(!checkTheValidBankAccount(houseId)){
//			 throw new BusinessException("house:pro_right_bankaccount_error_exception",
//						BusinessException.WARNING);

		 //出盘还没回盘操作的不能进行退伙
		 BankAccountDomain bankAccount = bankAccountDao.getBankAccountByHouseId(houseId, true);
		 if(!BlankUtil.isBlank(bankAccount)){
			if(!collectionService.isIn(bankAccount.getAccNumber())){
				throw new BusinessException("house:pro_right_bankaccount_isin_exception",
						BusinessException.WARNING);
			}
		 }

	 }

	 /**
	  * 方法描述: 验证该产权房拥有正确有效的银行划款账号
	  * @author 胡煦
	  * Create on:2008-9-9
	  * @param houseId
	  * @return boolean:true说明拥有正确有效的帐户,反之说明没有
	  * Edit author:
	  * Edit on:
	  * 修改原因：
	  */
	 public boolean checkTheValidBankAccount(Long houseId){
		 return bankAccountDao.getBankAccountByHouseId(houseId, true) != null;
	 }

	 /**
	 * 方法描述:  变为历史业主方法
	 * @author 胡煦
	 * Create on:2008-9-2
	 * @param Long goOutId,Long houseId
	 * @return boolean
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public boolean changeToHisOwers(Long goOutId,Long createrId){
		 GoOutDomain goOutDomain = goOutDao.findById(goOutId);
		 if(!BlankUtil.isBlank(goOutDomain)){
			 Long houseId = goOutDomain.getHouse().getKeyword();
			 //验证变为历史业主操作是否合法
			 checkChangeToHisOwers(goOutDomain);
			 //更新为退伙结束状态
			 goOutDomain.setGoOutStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_GO_OUT_FLOW,  SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_END));
			 modifyInfo(goOutDomain.getSysInfo(),createrId);
			 //更新房屋状态
			 goOutDomain.getHouse().setStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_HOUSE_HOUSE_STATUS_CODE, SysrefcodeDO.HM_HOUSE_HOUSE_STATUS_VALUE_VACANT));
			 modifyInfo(goOutDomain.getHouse().getSysInfo(),createrId);
			 //更新房屋产权状态
			 ProRightDO proRightDO = proRightDao.getEffectiveProRightByHouseId(houseId);
			 if(!BlankUtil.isBlank(proRightDO)){
				 //更新房屋ID对应的产权ID为无效状态
				 proRightDO.setValidity(SysrefcodeDO.CONSTANTS_DIGITAL_ZERO);
				 modifyInfo(proRightDO.getSysInfo(), createrId);
				 proRightDao.updateObject(proRightDO);
			 }
			 //解除房屋和客户之间的关系
			 List<ClientRHouseDO> clientRHouseDOs = clientRHouseDao.getClientRHouseListByHouseIdAndProRight(houseId, proRightDO.getProRightId(),SysrefcodeDO.CLIENT_TYPE_OWNER);
			 if(clientRHouseDOs.size() >0 ){
				 for(ClientRHouseDO clientRHouseDO : clientRHouseDOs){
					 clientRHouseDO.setValidity(SysrefcodeDO.CONSTANTS_DIGITAL_ZERO);
					 clientRHouseDao.updateObject(clientRHouseDO);
				 }
			 }
			 //更新帐户的状态,屏蔽与房屋ID和产权ID对应的帐户
			 AccountDomain accountDomain = accountDao.getAccountBy(proRightDO.getProRightId(), houseId, true);
			 if(!BlankUtil.isBlank(accountDomain)){
				 accountDomain.setIsActive(SysrefcodeDO.CONSTANTS_DIGITAL_ZERO);
				 modifyInfo(accountDomain.getSysInfo(), createrId);
				 accountDao.updateObject(accountDomain);
			 }
			 //修改子帐户状态
			 ChargeAccountDomain subAccount = subAccountDao.getChargeAccountDoBy(houseId);
			 //同时锁定”借”和”贷”
			 if(!BlankUtil.isBlank(subAccount)){
				 subAccountService.lockDC(subAccount.getSubAccountId());
			 }
			 //更新银行划款帐号,屏蔽与房屋ID和产权ID对应的银行划款帐号
			 BankAccountDomain bankAccountDo = bankAccountDao.getBankAccountByHouseId(houseId, true);
			 if(!BlankUtil.isBlank(bankAccountDo)){
				 bankAccountDo.setIsActive(SysrefcodeDO.CONSTANTS_DIGITAL_ZERO);
				 modifyInfo(bankAccountDo.getSysInfo(), createrId);
				 bankAccountDao.updateObject(bankAccountDo);
			 }
		 }
		 return true;
	 }



	 /**
	 * 方法描述: 验证变为历史业主操作是否合法
	 *A、该退伙ID对应产权房的帐户费用款项全部都缴清
	 *B、退伙登记的退伙状态处于‘审核完毕’
	 * @author 胡煦
	 * Create on:2008-9-11
	 * @param nameStr：查询条件班级名称
	 * @return 返回当前页的查询结果
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 private boolean checkChangeToHisOwers(GoOutDomain goOutDomain){
		 BigDecimal balance = accountService.getBalance(goOutDomain.getHouse().getKeyword());
		 //该退伙ID对应产权房的帐户费用款项全部都缴清
		 if(balance.compareTo(new BigDecimal(0)) != 0){
			 throw new BusinessException("house:pro_right_change_ower_blance_exception",
						BusinessException.WARNING);
		 }
		 //验证该产权房的帐户是否存在挂起交易
		 this.checkTheGoOutHasHangS(goOutDomain.getHouse().getKeyword());

		 //退伙登记的退伙状态处于‘审核完毕’
		 if(!SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_FINISH.equals(goOutDomain.getGoOutStatus().getValue())){
			 throw new BusinessException("house:pro_right_goout_status_error_exception",
						BusinessException.WARNING);
		 }
		 //验证是否存在新建走表数据
		 this.checkHasNewMeterDatas(goOutDomain.getHouse().getKeyword());
		 return true;
	 }

	 /**
	 * 方法描述: 退伙手续审核
	 * @author 胡煦
	 * Create on:2008-9-10
	 * @param ExamineApproveVO examineApproveVO,String approveRole
	 * @return ExamineApproveVO
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public ExamineApproveVO goOutAuditing(ExamineApproveVO examineApproveVO,String approveRole){

		 ExamineApproveDomain approveDomain = examineApproveDao.getExamineApproveBy(examineApproveVO.getGoOutId(),approveRole);
		 //验证退伙手续审核合法性
		 checkAuditing(examineApproveVO.getGoOutId(), approveRole,examineApproveVO.getUserId());
		 //如果退伙手续审核结果为不通过，同时更新退伙登记表中的退伙状态为新建状态
		if(SysrefcodeDO.HM_EXAMINE_APPROVE_AUDITING_NOPASS.equals(examineApproveVO.getExamineActionCode())){
			approveDomain.setConsequence(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_EXAMINE_APPROVE_AUDITING_ACTION, SysrefcodeDO.HM_EXAMINE_APPROVE_AUDITING_NOPASS));
			approveDomain.setExamineDate(examineApproveVO.getExamineDate());
			modifyInfo(approveDomain.getSysInfo(), examineApproveVO.getModifierId());
			approveDomain.setNotion(examineApproveVO.getNotion());
			approveDomain.getGoOut().setGoOutStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_GO_OUT_FLOW,  SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_NEW));
			modifyInfo(approveDomain.getGoOut().getSysInfo(), examineApproveVO.getModifierId());

			//退伙审批不通过,解除账户锁定
			//获取当前收费周期该走表数据对应的收费交易账户
			ChargeAccountDomain accountDomain = subAccountDao.getChargeAccountDoBy(approveDomain.getGoOut().getHouse().getKeyword());
			if(subAccountService.isLockDebit(accountDomain.getSubAccountId())){
				subAccountService.unblockDebit(accountDomain.getSubAccountId());
			}
			//String lockState = accountDomain.getLockState();
			//accountDomain.setLockState(SysrefcodeDO.CONSTANTS_DIGITAL_ZERO+lockState.substring(1, 2));
		}
		//如果退伙手续审核结果为通过，则根据退伙ID查询退伙登记表中的退伙状态，
		if(SysrefcodeDO.HM_EXAMINE_APPROVE_AUDITING_PASS.equals(examineApproveVO.getExamineActionCode())){
			approveDomain.setConsequence(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_EXAMINE_APPROVE_AUDITING_ACTION, SysrefcodeDO.HM_EXAMINE_APPROVE_AUDITING_PASS));
			approveDomain.setExamineDate(examineApproveVO.getExamineDate());
			approveDomain.setNotion(examineApproveVO.getNotion());
			modifyInfo(approveDomain.getSysInfo(), examineApproveVO.getModifierId());
			//退伙财务经理审批通过,锁定账户为不容许应收交易
			if(SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_FINANCE.equals(approveRole)){
				//获取当前收费周期该走表数据对应的收费交易账户
				ChargeAccountDomain accountDomain = subAccountDao.getChargeAccountDoBy(approveDomain.getGoOut().getHouse().getKeyword());
				if(!subAccountService.isLockDebit(accountDomain.getSubAccountId())){
					subAccountService.lockDebit(accountDomain.getSubAccountId());
				}
			}
			//(1)如果退伙状态为待审核，则更新退伙登记表中的退伙状态为审核中；
			if(SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_WAIT.equals(approveDomain.getGoOut().getGoOutStatus().getValue())){
				approveDomain.setNotion(examineApproveVO.getNotion());
				approveDomain.getGoOut().setGoOutStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_GO_OUT_FLOW,  SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_DO));
				modifyInfo(approveDomain.getGoOut().getSysInfo(), examineApproveVO.getModifierId());
			}else{
				//(2)如果退伙状态为审核中，则更新退伙登记表中的退伙状态为审核完毕。
				if(SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_DO.equals(approveDomain.getGoOut().getGoOutStatus().getValue())){
					approveDomain.setNotion(examineApproveVO.getNotion());
					approveDomain.getGoOut().setGoOutStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_GO_OUT_FLOW,  SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_FINISH));
					modifyInfo(approveDomain.getGoOut().getSysInfo(), examineApproveVO.getModifierId());
				}
			}
		}
		 return examineApproveVO;
	 }

	 /**
	 * 方法描述: 退伙手续反审核
	 * @author 胡煦
	 * Create on:2008-9-11
	 * @param nameStr：查询条件班级名称
	 * @return 返回当前页的查询结果
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public ExamineApproveVO goOutReverseAuditing(ExamineApproveVO examineApproveVO,String approveRole){

		ExamineApproveDomain approveDomain = examineApproveDao.getExamineApproveBy(examineApproveVO.getGoOutId(),approveRole);
		//验证退伙手续反审核合法性
		this.checkReverseAuditing(approveDomain.getGoOut().getKeyword(), approveRole, approveDomain.getUserId());
		//更新该退伙手续的审核动作为反审核
		approveDomain.setNotion(examineApproveVO.getNotion());
		approveDomain.setConsequence(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_EXAMINE_APPROVE_AUDITING_ACTION, SysrefcodeDO.HM_EXAMINE_APPROVE_AUDITING_REVERSE));
		approveDomain.setExamineDate(examineApproveVO.getExamineDate());
		modifyInfo(approveDomain.getSysInfo(), examineApproveVO.getModifierId());

		//获取当前收费周期该走表数据对应的收费交易账户
		ChargeAccountDomain accountDomain = subAccountDao.getChargeAccountDoBy(approveDomain.getGoOut().getHouse().getKeyword());
		//解除账户锁定
		if(subAccountService.isLockDebit(accountDomain.getSubAccountId())){
			subAccountService.unblockDebit(accountDomain.getSubAccountId());
		}
		//同时修改退伙登记表中对应退伙ID的退伙状态为新建状态
		approveDomain.getGoOut().setGoOutStatus(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_GO_OUT_FLOW,  SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_NEW));
		modifyInfo(approveDomain.getGoOut().getSysInfo(), examineApproveVO.getModifierId());
		return examineApproveVO;
	 }

//	 /**
//	 * 方法描述: 根据退伙登记ＩＤ和审核角色查询ExamineApproveDomain
//	 * @author 胡煦
//	 * Create on:2008-9-11
//	 * @param nameStr：查询条件班级名称
//	 * @return 返回当前页的查询结果
//	 * Edit author:
//	 * Edit on:
//	 * 修改原因：
//	 */
//	 public ExamineApproveVO getExamineApproveBy(Long goOutId,String approveRole){
//
//		 ExamineApproveDomain approveDomain = examineApproveDao.getExamineApproveBy(goOutId,approveRole);
//
//
//	 }

	 /**
		 * 方法描述: 验证退伙手续审核合法性
		 * 1、如果对应的退伙ID的审核状态为“新建”、“审核完毕”和“退伙结束”，则不能进行审核操作。
		 * 2、审核人对指定的退伙记录进行审核时，如果该审核记录已经存在审核动作，则不能再次进行审核操作，只能执行反审核操作。
		 * @author 胡煦
		 * Create on:2008-9-11
		 * @param Long goOutId,String approveRole,Long userId
		 * @return boolean
		 * Edit author:
		 * Edit on:
		 * 修改原因：
		 */
		 public boolean checkAuditing(Long goOutId,String approveRole,Long userId){
			 super.checkParameterIsNull("common:parameters_null_exception, ", goOutId,userId);
			 ExamineApproveDomain approveDomain = examineApproveDao.getExamineApproveBy(goOutId,approveRole);
			 GoOutDomain goOutDomain = approveDomain.getGoOut();
			 // 如果对应的退伙ID的审核状态为“新建”、“审核完毕”和“退伙结束”，则不能进行审核操作。
			 if(goOutDomain.getGoOutStatus().getValue().equals(SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_NEW)||
					 goOutDomain.getGoOutStatus().getValue().equals(SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_FINISH)||
					 goOutDomain.getGoOutStatus().getValue().equals(SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_END)){
				throw new BusinessException("house:house_auditing_status_exception",
						BusinessException.WARNING);
			 }
			//审核人对指定的退伙记录进行审核时，如果该审核记录已经存在审核动作，则不能再次进行审核操作，只能执行反审核操作。
			if(!BlankUtil.isBlank(approveDomain.getConsequence())){
				throw new BusinessException("house:house_auditing_status_exist_exception",
							BusinessException.WARNING);
			}
			//退伙记录必须由指定的审核人进行审核
			if(approveDomain.getUserId().compareTo(userId)!=0){
				throw new BusinessException("house:pro_right_auditing_pepole_error_exception",
							BusinessException.WARNING);
			}
			return true;
		 }

	 /**
	 * 方法描述: 验证退伙手续反审核合法性
	 * 该审核角色只有退伙审核表中审核动作不为空，
	 * 并且退伙登记表中退伙状态处于审核中或者审核完毕才能进行反审核操作，
	 * 另外，任何进行反审核的记录其审核人要与执行审核过程中的审核人是同一个人
	 * @author 胡煦
	 * Create on:2008-9-11
	 * @param Long goOutId,String approveRole,Long userId
	 * @return boolean
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public boolean checkReverseAuditing(Long goOutId,String approveRole,Long userId){
		 ExamineApproveDomain approveDomain = examineApproveDao.getExamineApproveBy(goOutId,approveRole);
		 GoOutDomain goOutDomain = approveDomain.getGoOut();

		 //该审核角色退伙审核表中审核动作不能为空
		if(BlankUtil.isBlank(approveDomain.getConsequence())){
			throw new BusinessException("house:house_reverseauditing_status_null_exception",
					BusinessException.WARNING);
		}
		//退伙登记表中退伙状态处于审核中或者审核完毕才能进行反审核操作
		if(!SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_DO.equals(goOutDomain.getGoOutStatus().getValue())&&
				!SysrefcodeDO.HM_GO_OUT_FLOW_AUDIT_FINISH.equals(goOutDomain.getGoOutStatus().getValue())){
			throw new BusinessException("house:house_reverseauditing_status_error_exception",
					BusinessException.WARNING);
		}
		//任何进行反审核的记录其审核人要与执行审核过程中的审核人是同一个人
		if(approveDomain.getUserId().compareTo(userId) != 0){
			throw new BusinessException("house:house_reverseauditing_user_error_exception",
					BusinessException.WARNING);
		}
		return true;
	 }


	 /**
	 * 方法描述: 查找所有用户,主要是为页面下拉框显示服务
	 * @author 胡煦
	 * Create on:2008-9-9
	 * @param
	 * @return Page
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
//	public Page getAllUser(String userName,int pageNo, int pageSize){
//		Page page = examineApproveDao.getAllUser(userName,pageNo,pageSize);
//		List<Object[]> list = page.getResult();
//		List<UserVO> userVOList = new ArrayList<UserVO>();
//		for(Object[] objects : list){
//			UserVO userVO = new UserVO( Long.parseLong((objects[0].toString())), objects[6].toString());
//			userVOList.add(userVO);
//		}
//		page.setResult(userVOList);
//		return page;
//	 }

	 /**
	 * 方法描述: 查询所有的移交物品,主要是为页面下拉框显示服务
	 * @author 胡煦
	 * Create on:2008-9-9
	 * @param nameStr：查询条件班级名称
	 * @return 返回当前页的查询结果
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 public List<GoodsRecordDomain> getAllGoodsRecords(){
		return goodsRecordDao.getAllGoodsRecords();
	 }

	 /**
	 * 方法描述: 验证是否存在新建走表数据
	 * @author 胡煦
	 * Create on:2008-12-6
	 * @param houseId
	 * @return void
	 * Edit author:
	 * Edit on:
	 * 修改原因：
	 */
	 private void checkHasNewMeterDatas(Long houseId){
		List<ChargeDatasDomain> list = meterDataRegisterDao.getNewMeterDatasListByHouseId(houseId);
		if(list.size() > 0){
			throw new BusinessException("house:pro_right_change_hasnewdata_exception",
					BusinessException.WARNING);
		}
	 }

	 private GoOutVO addExamineApprove(GoOutVO goOutVO){

		 //新增财务经理审核记录
		 goOutVO.setChargeCheckId(this.addExamineApproveBy(goOutVO, SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_FINANCE).getKeyword());
		 //新增客服经理审核记录
		 goOutVO.setOutCheckId(this.addExamineApproveBy(goOutVO, SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_CLIENT).getKeyword());

		 return goOutVO;
	 }

	 private ExamineApproveDomain addExamineApproveBy(GoOutVO goOutVO,String approveRole){

		 ExamineApproveDomain examineApproveDomain = new ExamineApproveDomain();

		 if(!BlankUtil.isBlank(goOutVO.getCreatorId())){
			 examineApproveDomain.setSysInfo(createInfo(goOutVO.getCreatorId()));
		 }else{
			 examineApproveDomain.setSysInfo(createInfo(goOutVO.getModifierId()));
		 }
		 examineApproveDomain.setNotion(goOutVO.getNotion());
		 examineApproveDomain.setGoOut(goOutDao.findById(goOutVO.getKeyword()));
		 examineApproveDomain.setExamineDate(goOutVO.getExamineDate());
		 if(SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_FINANCE.equals(approveRole)){
			 examineApproveDomain.setUserId(goOutVO.getChargeCheckerId());
		 }
		 if(SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_CLIENT.equals(approveRole)){
			 examineApproveDomain.setUserId(goOutVO.getOutCheckerId());
		 }
		 examineApproveDomain.setValidity(SysrefcodeDO.CONSTANTS_DIGITAL_ONE);
		 examineApproveDomain.setApproveRole(sysrefcodeDao.getSysrefCodesByCode(SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE, approveRole));

		 return  examineApproveDao.saveObject(examineApproveDomain);
	 }

	 private GoOutVO editExamineApprove(GoOutVO goOutVO){
		 //修改客服经理审核记录
		 this.editExamineApproveBy(goOutVO, SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_CLIENT);
		 //建立客服经理退伙审核记录
		 goOutVO.setOutCheckId(this.addExamineApproveBy(goOutVO, SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_CLIENT).getKeyword());
		 //修改财务经理审核记录
		 this.editExamineApproveBy(goOutVO, SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_FINANCE);
		 //建立财务经理退伙审核记录
		 goOutVO.setChargeCheckId(this.addExamineApproveBy(goOutVO, SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_FINANCE).getKeyword());
		 return goOutVO;
	 }

	 private GoOutVO editExamineApproveBy(GoOutVO goOutVO ,String approveRole){

		 //根据退伙登记和审核角色得到相宜审核记录
		 ExamineApproveDomain examineApproveDomain = examineApproveDao.getExamineApproveBy(goOutVO.getKeyword(), approveRole);

		 modifyInfo(examineApproveDomain.getSysInfo(), goOutVO.getModifierId());

		 examineApproveDomain.setValidity(SysrefcodeDO.CONSTANTS_DIGITAL_ZERO);

		 if(SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_FINANCE.equals(approveRole)){
			 if(BlankUtil.isBlank(goOutVO.getChargeCheckerId())){
				 goOutVO.setChargeCheckerId(examineApproveDomain.getUserId());
			 }
		 }
		 if(SysrefcodeDO.HM_EXAMINE_APPROVE_USER_ROLE_CLIENT.equals(approveRole)){
			 if(BlankUtil.isBlank(goOutVO.getOutCheckerId())){
				 goOutVO.setOutCheckerId(examineApproveDomain.getUserId());
			 }
		 }
		 examineApproveDomain.setExamineDate(goOutVO.getExamineDate());
		 examineApproveDao.updateObject(examineApproveDomain);

		 return goOutVO;
	 }

	 private CopyMeterData addMeterData(GoOutVO goOutVO,String meterTypeCode){
		 //处理新增的走表数据
		 OriginalMeterDataVO originalMeterDataVO = addOriginalMeterData(goOutVO, meterTypeCode);
		 return addCopyMeterData(goOutVO, originalMeterDataVO, meterTypeCode);
	 }

	 private OriginalMeterDataVO addOriginalMeterData(GoOutVO goOutVO,String meterTypeCode){
		 //添加走表原始数据
		OriginalMeterDataVO originalMeterDataVO = new OriginalMeterDataVO();
		originalMeterDataVO.setOwners(goOutVO.getClients());
		originalMeterDataVO.setHouseId(goOutVO.getHouseId());
		originalMeterDataVO.setCreator(goOutVO.getCreatorId()==null?goOutVO.getModifierId():goOutVO.getCreatorId());
		originalMeterDataVO.setMeterType(meterTypeCode);
		originalMeterDataVO.setRecordTime(goOutVO.getCopyTime());
		if(SysrefcodeDO.HM_WATER_METER_TYPE_CODE.equals(meterTypeCode)){
			originalMeterDataVO.setThisReading(goOutVO.getCopyMeterWaterReading());
			originalMeterDataVO.setLastReading(goOutVO.getCopyMeterWaterPreReading());
		}
		if(SysrefcodeDO.HM_AMMETER_METER_TYPE_CODE.equals(meterTypeCode)){
			originalMeterDataVO.setThisReading(goOutVO.getCopyMeterAmmeterReading());
			originalMeterDataVO.setLastReading(goOutVO.getCopyMeterAmmeterPreReading());
		}
		originalMeterDataVO = meterDataRegisterService.addOriginalMeterData(originalMeterDataVO);

		//获取当前收费周期该走表数据对应的收费交易账户
		//DebitTransDomain debitTransDomain = debitTransDao.getTransDomainBy(originalMeterDataVO.getChargeDataId());
		ChargeAccountDomain accountDomain = subAccountDao.getChargeAccountDoBy(goOutVO.getHouseId());
		ChargeDatasDomain newChargeDatas = meterDataRegisterDao.findById(originalMeterDataVO.getChargeDataId());
		arCalculateService.calculate(accountDomain, newChargeDatas, null, goOutVO.getModifierId()==null?goOutVO.getCreatorId():goOutVO.getModifierId());
		return originalMeterDataVO;
	 }

	 private OriginalMeterDataVO editOriginalMeterData(GoOutVO goOutVO,Long chargeDataId,String meterTypeCode,String statuz){
		 //修改走表原始数据
		OriginalMeterDataVO originalMeterDataVO = meterDataRegisterService.findMeterDataVOByID(chargeDataId);
		originalMeterDataVO.setOwners(goOutVO.getClients());
		originalMeterDataVO.setHouseId(goOutVO.getHouseId());
		originalMeterDataVO.setMeterType(meterTypeCode);
		originalMeterDataVO.setRecordTime(goOutVO.getCopyTime());
		originalMeterDataVO.setStatuz(statuz);
		originalMeterDataVO.setCreator(goOutVO.getModifierId());
		//设置水表读数
		if(SysrefcodeDO.HM_WATER_METER_TYPE_CODE.equals(meterTypeCode)){
			originalMeterDataVO.setThisReading(goOutVO.getCopyMeterWaterReading());
			originalMeterDataVO.setLastReading(goOutVO.getCopyMeterWaterPreReading());
		}
		//设置电表读数
		if(SysrefcodeDO.HM_AMMETER_METER_TYPE_CODE.equals(meterTypeCode)){
			originalMeterDataVO.setThisReading(goOutVO.getCopyMeterAmmeterReading());
			originalMeterDataVO.setLastReading(goOutVO.getCopyMeterAmmeterPreReading());
		}
		originalMeterDataVO = meterDataRegisterService.editOriginalMeterDataBy(originalMeterDataVO,true);
		//获取当前收费周期该走表数据对应的收费交易账户
		//DebitTransDomain debitTransDomain = debitTransDao.getTransDomainBy(originalMeterDataVO.getChargeDataId());
		ChargeAccountDomain accountDomain = subAccountDao.getChargeAccountDoBy(goOutVO.getHouseId());
		ChargeDatasDomain newChargeDatas = null;
		if(!BlankUtil.isBlank(originalMeterDataVO.getChargeDataId())){
			newChargeDatas = meterDataRegisterDao.findById(originalMeterDataVO.getChargeDataId());
			arCalculateService.calculate(accountDomain, newChargeDatas, chargeDataId,goOutVO.getModifierId()==null?goOutVO.getCreatorId():goOutVO.getModifierId());
		}

		return originalMeterDataVO;
	 }

	 private CopyMeterData addCopyMeterData(GoOutVO goOutVO,OriginalMeterDataVO originalMeterDataVO,String meterTypeCode){
		//添加抄表记录
		CopyMeterData copyMeterData = new CopyMeterData();
		copyMeterData.setChargeDataId(originalMeterDataVO.getChargeDataId());
		copyMeterData.setSysInfo(createInfo(goOutVO.getCreatorId()==null?goOutVO.getModifierId():goOutVO.getCreatorId()));
		copyMeterData.setCopyTime(goOutVO.getCopyTime());
		copyMeterData.setMeter(meterDao.findById(originalMeterDataVO.getMeterId()));
		//设置水表读数
		if(SysrefcodeDO.HM_WATER_METER_TYPE_CODE.equals(meterTypeCode)){
			copyMeterData.setReading(goOutVO.getCopyMeterWaterReading());
			copyMeterData.setPreReading(goOutVO.getCopyMeterWaterPreReading());
		}
		//设置电表读数
		if(SysrefcodeDO.HM_AMMETER_METER_TYPE_CODE.equals(meterTypeCode)){
			copyMeterData.setReading(goOutVO.getCopyMeterAmmeterReading());
			copyMeterData.setPreReading(goOutVO.getCopyMeterAmmeterPreReading());
		}
		copyMeterData = copyMeterDataDao.saveObject(copyMeterData);
		return copyMeterData;
	 }

	 private CopyMeterData editCopyMeterData(GoOutVO goOutVO,CopyMeterData copyMeterData,OriginalMeterDataVO originalMeterDataVO){
		//修改抄表记录
		copyMeterData.setChargeDataId(originalMeterDataVO.getChargeDataId());
		modifyInfo(copyMeterData.getSysInfo(), goOutVO.getModifierId());
		copyMeterData.setCopyTime(goOutVO.getCopyTime());
		copyMeterData.setMeter(meterDao.findById(originalMeterDataVO.getMeterId()));
		//设置水表读数
		if(SysrefcodeDO.HM_WATER_METER_TYPE_CODE.equals(copyMeterData.getMeter().getMeterType().getCode())){
			copyMeterData.setReading(goOutVO.getCopyMeterWaterReading());
			copyMeterData.setPreReading(goOutVO.getCopyMeterWaterPreReading());
		}
		//设置电表读数
		if(SysrefcodeDO.HM_AMMETER_METER_TYPE_CODE.equals(copyMeterData.getMeter().getMeterType().getCode())){
			copyMeterData.setReading(goOutVO.getCopyMeterAmmeterReading());
			copyMeterData.setPreReading(goOutVO.getCopyMeterAmmeterPreReading());
		}

		return copyMeterDataDao.updateObject(copyMeterData);
	}

	 private CopyMeterData editMeterDataByType(GoOutVO goOutVO,CopyMeterData copyMeterData,String meterTypeCode,BigDecimal copyMeterReading){
		 //如果抄表ID为空且输入的读数不为空，则新增表读数
		if(BlankUtil.isBlank(copyMeterData)&&!BlankUtil.isBlank(copyMeterReading)){
			return this.addMeterData(goOutVO, meterTypeCode);
		}
		//如果抄表ID不为空且输入的表读数不为空
		if(!BlankUtil.isBlank(copyMeterData)&&!BlankUtil.isBlank(copyMeterReading)){
			//如果本次抄表数据 = 输入的表读数和抄表时间不变 , 则退出水表读数处理。
			if(copyMeterData.getReading().compareTo(copyMeterReading)==0&&
					copyMeterData.getCopyTime().equals(goOutVO.getCopyTime())){
				return copyMeterData;
			}//如果本次抄表数据 = 输入的表读数和抄表时间改变 , 则直接更新抄表时间。
			else if(copyMeterData.getReading().compareTo(copyMeterReading)==0&&
						!copyMeterData.getCopyTime().equals(goOutVO.getCopyTime())){
				ChargeDatasDomain chargeDatasDomain	= meterDataRegisterDao.findById(copyMeterData.getChargeDataId());
				chargeDatasDomain.setRecordTime(goOutVO.getCopyTime());
				copyMeterData.setCopyTime(goOutVO.getCopyTime());
				modifyInfo(copyMeterData.getSysInfo(), goOutVO.getModifierId());
				copyMeterDataDao.updateObject(copyMeterData);
				return copyMeterData;
			}
			OriginalMeterDataVO originalMeterDataVO = this.editOriginalMeterData(goOutVO,copyMeterData.getChargeDataId(), meterTypeCode,SysrefcodeDO.FEE_CHARGE_DATAS_STATUS_EDIT);
			return this.editCopyMeterData(goOutVO, copyMeterData, originalMeterDataVO);
		}
		//如果抄表ID不为空且输入的表读数为空
		if(!BlankUtil.isBlank(copyMeterData)&&BlankUtil.isBlank(copyMeterReading)){

			ChargeDatasDomain chargeDatasDomain	= meterDataRegisterDao.findById(copyMeterData.getChargeDataId());

			//对应表读数状态为新建状态
			if(SysrefcodeDO.FEE_CHARGE_DATAS_STATUS_NEW.equals(chargeDatasDomain.getStatuz())){
				//作废表FEE_CHARGE_DATAS中一条水表读数。
				meterDataRegisterService.abateMeterDataById(copyMeterData.getChargeDataId(), goOutVO.getCreatorId());
				//删除表CS_COPY_METER_DATA中已有的水表读数
				copyMeterDataDao.deleteObject(copyMeterData);
				return null;
			}
//			//获取当前收费周期该走表数据对应的收费交易
//			List<DebitTransDomain> debitTransDomains = debitTransDao.getTransDomainBy(copyMeterData.getChargeDataId());
			//对应表读数状态为已计算,对应费用是未缴费状态
			if((SysrefcodeDO.FEE_CHARGE_DATAS_STATUS_COUNTED.equals(chargeDatasDomain.getStatuz()))){
				//meterDataRegisterService.checkEditMeterDataState(copyMeterData.getChargeDataId(),true);
				//此处调用走表原始数据的修改操作
				this.editOriginalMeterData(goOutVO,copyMeterData.getChargeDataId(), meterTypeCode,SysrefcodeDO.FEE_CHARGE_DATAS_STATUS_ABATE);
				//删除表CS_COPY_METER_DATA中已有的水表读数
				copyMeterDataDao.deleteObject(copyMeterData);
			}
			return null;
		}
		return null;
	 }

//	 /**
//	 * 方法描述: 根据退伙财务经理审批结果修改子帐户状态
//	 * @author 胡煦
//	 * Create on:2008-10-13
//	 * @param
//	 * @return
//	 * Edit author:
//	 * Edit on:
//	 * 修改原因：
//	 */
//	 private void checkDebitTransStatus(){
//
//	 }


	 private ExamineApproveVO convertGoOutDoToVo(ExamineApproveDomain examineApproveDomain){
		 ExamineApproveVO examineApproveVO = new ExamineApproveVO();
		 if(BlankUtil.isBlank(examineApproveDomain)){
			 return examineApproveVO;
		 }
		 PopulateUtil.populate(examineApproveDomain, examineApproveVO);
		 examineApproveVO.setExamineDate(examineApproveDomain.getExamineDate());
		 examineApproveVO.setExamineActionCode(examineApproveDomain.getConsequence()==null?null:examineApproveDomain.getConsequence().getValue());
		 examineApproveVO.setUserName(secUserDao.queryUserNameById(examineApproveDomain.getUserId()));
		 examineApproveVO.setType(examineApproveDomain.getApproveRole().getName());
		 return examineApproveVO;
	 }

//	 private ExamineApproveVO convertGoOutVoToDo(ExamineApproveVO examineApproveVO){
//	 }

	 private GoOutVO convertGoOutDoToVo(GoOutDomain goOutDomain){
		GoOutVO goOutVO = new GoOutVO();
		if(BlankUtil.isBlank(goOutDomain)){
			return goOutVO;
		}
		PopulateUtil.populate(goOutDomain, goOutVO);

		goOutVO.setHouseId(goOutDomain.getHouse().getKeyword());

		goOutVO.setHouseNumber(goOutDomain.getHouse().getHouseNumber());

		goOutVO.setStatuName(goOutDomain.getGoOutStatus().getName());
		goOutVO.setStatuCode(goOutDomain.getGoOutStatus().getValue());

		goOutVO.setCopyMeterWaterReading(goOutDomain.getCopyMeterData1()==null?null:goOutDomain.getCopyMeterData1().getReading());
		goOutVO.setCopyMeterWaterPreReading(goOutDomain.getCopyMeterData1()==null?null:goOutDomain.getCopyMeterData1().getPreReading());

		goOutVO.setCopyMeterAmmeterReading(goOutDomain.getCopyMeterData2()==null?null:goOutDomain.getCopyMeterData2().getReading());
		goOutVO.setCopyMeterAmmeterPreReading(goOutDomain.getCopyMeterData2()==null?null:goOutDomain.getCopyMeterData2().getPreReading());

		goOutVO.setCopyMeterAmmeterId(goOutDomain.getCopyMeterData2()==null?null:goOutDomain.getCopyMeterData2().getKeyword());
		goOutVO.setCopyMeterWaterId(goOutDomain.getCopyMeterData1()==null?null:goOutDomain.getCopyMeterData1().getKeyword());

		goOutVO.setCopyTime(goOutDomain.getCopyMeterDate());

		goOutVO.setCopyMeterReasonId(goOutDomain.getReasonDef1()==null?null:goOutDomain.getReasonDef1().getKeyword());
		goOutVO.setCopyMeterReasonName(goOutDomain.getReasonDef1()==null?null:goOutDomain.getReasonDef1().getName());
		goOutVO.setCopyMeterReasonDesc(goOutDomain.getReasonDef1()==null?null:goOutDomain.getReasonDef1().getDescription());

		goOutVO.setCheckReasonId(goOutDomain.getReasonDef2()==null?null:goOutDomain.getReasonDef2().getKeyword());
		goOutVO.setCheckReasonName(goOutDomain.getReasonDef2()==null?null:goOutDomain.getReasonDef2().getName());
		goOutVO.setCheckReasonDesc(goOutDomain.getReasonDef2()==null?null:goOutDomain.getReasonDef2().getDescription());

		goOutVO.setHandoverReasonId(goOutDomain.getReasonDef3()==null?null:goOutDomain.getReasonDef3().getKeyword());
		goOutVO.setHandoverReasonName(goOutDomain.getReasonDef3()==null?null:goOutDomain.getReasonDef3().getName());
		goOutVO.setHandoverReasonDesc(goOutDomain.getReasonDef3()==null?null:goOutDomain.getReasonDef3().getDescription());

		//设置移交物品
		if(!BlankUtil.isBlank(goOutDomain.getGoods())){
			List<Long> list = new ArrayList<Long>();
			List<String> strList = new ArrayList<String>();
			for(GoodsRecordDomain recordDomain :goOutDomain.getGoods()){
				list.add(recordDomain.getKeyword());
				strList.add(recordDomain.getName());
			}
			Object[] longs = list.toArray();
			Object[] strings = strList.toArray();
			goOutVO.setGoodIds(StringAnalysiUtil.portfolioFormattedString(longs));
			goOutVO.setGoods(StringAnalysiUtil.portfolioFormattedString(strings));
		}

		return goOutVO;
	}

	private GoOutDomain convertGoOutVoToDo(GoOutVO goOutVO){

		GoOutDomain goOutDomain = new GoOutDomain();

		if(BlankUtil.isBlank(goOutVO)){
			return goOutDomain;
		}

		PopulateUtil.populate(goOutVO, goOutDomain);

		if(!BlankUtil.isBlank(goOutVO.getGoodIds())){
			//建立退伙移交物品关系
			Set<GoodsRecordDomain> set = new HashSet<GoodsRecordDomain>();
			set.addAll(goodsRecordDao.findGoodsRecordsByIds(goOutVO.getGoodIds()));
			//先清空再添加
			if(!BlankUtil.isBlank(goOutDomain.getGoods())){
				goOutDomain.getGoods().clear();
			}
			goOutDomain.setGoods(set);
		}
		goOutDomain.setCopyMeterDate(goOutVO.getCopyTime());

		goOutDomain.setHouse(houseDao.findById(goOutVO.getHouseId()));
		//set the water datas
		goOutDomain.setCopyMeterData1(goOutVO.getCopyMeterWaterId()==null?null:copyMeterDataDao.findById(goOutVO.getCopyMeterWaterId()));
		//set the Ammeter datas
		goOutDomain.setCopyMeterData2(goOutVO.getCopyMeterAmmeterId()==null?null:copyMeterDataDao.findById(goOutVO.getCopyMeterAmmeterId()));

		if(!BlankUtil.isBlank(goOutVO.getCopyMeterReasonId())){
			goOutDomain.setReasonDef1(reasonDefDao.findById(goOutVO.getCopyMeterReasonId()));
		}
		if(!BlankUtil.isBlank(goOutVO.getCheckReasonId())){
			goOutDomain.setReasonDef2(reasonDefDao.findById(goOutVO.getCheckReasonId()));
		}
		if(!BlankUtil.isBlank(goOutVO.getHandoverReasonId())){
			goOutDomain.setReasonDef3(reasonDefDao.findById(goOutVO.getHandoverReasonId()));
		}
		if(!BlankUtil.isBlank(goOutVO.getCreatorId())){
			goOutDomain.setSysInfo(createInfo(goOutVO.getCreatorId()));
		}
		return goOutDomain;
	}

	private IGoOutDao goOutDao;
	private IHouseDao houseDao;
	private IMeterDao meterDao;
	private IReasonDefDao reasonDefDao;
	private IGoodsRecordDao goodsRecordDao;
	private ICopyMeterDataDao copyMeterDataDao ;
	private IHouseService houseService;
	private IProRightDao proRightDao;
	private IMeterDataRegisterService meterDataRegisterService;
	private IExamineApproveDao examineApproveDao;
	private IMeterDataRegisterDao meterDataRegisterDao;
	private ICoalitionHouseDao coalitionHouseDao;
	private IAccountDao accountDao;
	private IBankAccountDao bankAccountDao;
	private IAccountService accountService;
	private IClientRHouseDao clientRHouseDao;
	private IArCalculateService arCalculateService;
	private ISubAccountDao subAccountDao;
	private ISecUserDao secUserDao;
	private IBankCollectionService collectionService;
	private ISubAccountService subAccountService;
	private ITransactionService transactionService;
	/**
	 * @param subAccountService the subAccountService to set
	 */
	public void setSubAccountService(ISubAccountService subAccountService) {
		this.subAccountService = subAccountService;
	}

	/**
	 * @param accountService the accountService to set
	 */
	public void setAccountService(IAccountService accountService) {
		this.accountService = accountService;
	}

	/**
	 * @param coalitionHouseDao the coalitionHouseDao to set
	 */
	public void setCoalitionHouseDao(ICoalitionHouseDao coalitionHouseDao) {
		this.coalitionHouseDao = coalitionHouseDao;
	}

	/**
	 * @param examineApproveDao the examineApproveDao to set
	 */
	public void setExamineApproveDao(IExamineApproveDao examineApproveDao) {
		this.examineApproveDao = examineApproveDao;
	}

	/**
	 * @param proRightDao the proRightDao to set
	 */
	public void setProRightDao(IProRightDao proRightDao) {
		this.proRightDao = proRightDao;
	}

	/**
	 * @param houseService the houseService to set
	 */
	public void setHouseService(IHouseService houseService) {
		this.houseService = houseService;
	}

	/**
	 * @param goOutDao the goOutDao to set
	 */
	public void setGoOutDao(IGoOutDao goOutDao) {
		this.goOutDao = goOutDao;
	}

	/**
	 * @param goodsRecordDao the goodsRecordDao to set
	 */
	public void setGoodsRecordDao(IGoodsRecordDao goodsRecordDao) {
		this.goodsRecordDao = goodsRecordDao;
	}

	/**
	 * @param houseDao the houseDao to set
	 */
	public void setHouseDao(IHouseDao houseDao) {
		this.houseDao = houseDao;
	}

	/**
	 * @param meterDao the meterDao to set
	 */
	public void setMeterDao(IMeterDao meterDao) {
		this.meterDao = meterDao;
	}

	/**
	 * @param reasonDefDao the reasonDefDao to set
	 */
	public void setReasonDefDao(IReasonDefDao reasonDefDao) {
		this.reasonDefDao = reasonDefDao;
	}

	/**
	 * @param copyMeterDataDao the copyMeterDataDao to set
	 */
	public void setCopyMeterDataDao(ICopyMeterDataDao copyMeterDataDao) {
		this.copyMeterDataDao = copyMeterDataDao;
	}

	/**
	 * @param meterDataRegisterService the meterDataRegisterService to set
	 */
	public void setMeterDataRegisterService(
			IMeterDataRegisterService meterDataRegisterService) {
		this.meterDataRegisterService = meterDataRegisterService;
	}

	/**
	 * @param meterDataRegisterDao the meterDataRegisterDao to set
	 */
	public void setMeterDataRegisterDao(IMeterDataRegisterDao meterDataRegisterDao) {
		this.meterDataRegisterDao = meterDataRegisterDao;
	}

	/**
	 * @param accountDao the accountDao to set
	 */
	public void setAccountDao(IAccountDao accountDao) {
		this.accountDao = accountDao;
	}

	/**
	 * @param bankAccountDao the bankAccountDao to set
	 */
	public void setBankAccountDao(IBankAccountDao bankAccountDao) {
		this.bankAccountDao = bankAccountDao;
	}

	/**
	 * @return the bankAccountDao
	 */
	public IBankAccountDao getBankAccountDao() {
		return bankAccountDao;
	}

	/**
	 * @param clientRHouseDao the clientRHouseDao to set
	 */
	public void setClientRHouseDao(IClientRHouseDao clientRHouseDao) {
		this.clientRHouseDao = clientRHouseDao;
	}

	/**
	 * @param secUserDao the secUserDao to set
	 */
	public void setSecUserDao(ISecUserDao secUserDao) {
		this.secUserDao = secUserDao;
	}

	/**
	 * @param arCalculateService the arCalculateService to set
	 */
	public void setArCalculateService(IArCalculateService arCalculateService) {
		this.arCalculateService = arCalculateService;
	}

	/**
	 * @param subAccountDao the subAccountDao to set
	 */
	public void setSubAccountDao(ISubAccountDao subAccountDao) {
		this.subAccountDao = subAccountDao;
	}

	/**
	 * @param transactionService the transactionService to set
	 */
	public void setTransactionService(ITransactionService transactionService) {
		this.transactionService = transactionService;
	}

	/**
	 * @param collectionService the collectionService to set
	 */
	public void setCollectionService(IBankCollectionService collectionService) {
		this.collectionService = collectionService;
	}


}
